// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import path = require('path');
import fs = require('fs');


var outputChannel: vscode.LogOutputChannel;  // 输出通道

/**
 * 输出信息到控制台上，输出通道为MyCoder
 * @param message 输出的文本信息
 */
export function myLog() {
	if (outputChannel === undefined) {
		outputChannel = vscode.window.createOutputChannel('images-preview-plugin', {
			log: true,
		});
	}
	return outputChannel;
}

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {

	const provider = new ImagesPreviewViewProvider(context.extensionUri);

	context.subscriptions.push(
		vscode.window.registerWebviewViewProvider(ImagesPreviewViewProvider.viewType, provider));

	myLog().info('images-preview-plugin is now active!');

	let addImageDirDisposable = vscode.commands.registerCommand('images-preview-plugin.addImagesDir', async (focusUri: vscode.Uri, selectedUris: vscode.Uri[]) => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		myLog().info(`images-preview-plugin--------------------`);

		if (focusUri === null) {
			vscode.window.showErrorMessage('Please select a dir!');
			myLog().error("Please select a dir!");
			return;
		}

		const focusFile = fs.lstatSync(focusUri.fsPath);
		if (!focusFile.isDirectory()) {
			vscode.window.showErrorMessage('Please select a dir!');
			myLog().error("Please select a dir!");
			return;
		}

		const imageSuffixs = vscode.workspace.getConfiguration().get<string[]>("images-preview-plugin.imageSuffix") || [];
		const fileList = getFils(selectedUris, (filePath: string) => {
			const parsedPath = path.parse(filePath);
			if (imageSuffixs.indexOf(parsedPath.ext.toLowerCase()) > -1) {
				return true;
			} else {
				myLog().error(`Unsupported file type! ${filePath}`);
				return false;
			}
		});

		provider.addImagesDir(focusUri.fsPath, fileList);

	});

	let allDelDisposable = vscode.commands.registerCommand('images-preview-plugin.allDel', async (focusUri: vscode.Uri, selectedUris: vscode.Uri[]) => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		myLog().info(`images-preview-plugin--------------------`);
		provider.allDelt();

	});

	let refreshDisposable = vscode.commands.registerCommand('images-preview-plugin.refresh', async (focusUri: vscode.Uri, selectedUris: vscode.Uri[]) => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		myLog().info(`images-preview-plugin--------------------`);
		provider.refresh();

	});

	let settingDisposable = vscode.commands.registerCommand('images-preview-plugin.setting', async (focusUri: vscode.Uri, selectedUris: vscode.Uri[]) => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		myLog().info(`images-preview-plugin--------------------`);
		provider.setting();
	});

	let copyImageNameDisposable = vscode.commands.registerCommand('images-preview-plugin.copyImageName', async (args) => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		myLog().info(`images-preview-plugin--------------------`);
		myLog().info(args);
		vscode.env.clipboard.writeText(args.basename)
	});


	context.subscriptions.push(addImageDirDisposable);
	context.subscriptions.push(allDelDisposable);
	context.subscriptions.push(refreshDisposable);
	context.subscriptions.push(settingDisposable);
	context.subscriptions.push(copyImageNameDisposable);
}

/**
 * 获取选中文件,或文件夹下的文件,不递归
 * @param selectedUris 
 */
function getFils(selectedUris: vscode.Uri[], callback: (path: string) => boolean) {
	const filePaths: string[] = [];
	for (let index = 0; index < selectedUris.length; index++) {
		const uri = selectedUris[index];
		var stat = fs.lstatSync(uri.fsPath);
		if (stat.isDirectory()) {
			const childFils = fs.readdirSync(uri.fsPath);
			for (let f = 0; f < childFils.length; f++) {
				const childFilePath = path.join(uri.fsPath, childFils[f]);
				var childStat = fs.lstatSync(childFilePath);
				if (childStat.isFile() && callback.call(childFilePath, childFilePath)) {
					filePaths.push(childFilePath);
				}
			}
		} else if (stat.isFile() && callback.call(uri.fsPath, uri.fsPath)) {
			filePaths.push(uri.fsPath);
		}
	}
	return filePaths;
}
// This method is called when your extension is deactivated
export function deactivate() {
	myLog().info('images-preview-plugin is now deactivate!');
}


class ImagesPreviewViewProvider implements vscode.WebviewViewProvider {

	public static readonly viewType = 'images-preview-plugin.ImagesPreviewView';

	private _view?: vscode.WebviewView;

	constructor(
		private readonly _extensionUri: vscode.Uri,
	) { }

	public resolveWebviewView(
		webviewView: vscode.WebviewView,
		context: vscode.WebviewViewResolveContext,
		_token: vscode.CancellationToken,
	) {

		this._view = webviewView;

		webviewView.webview.options = {
			// Allow scripts in the webview
			enableScripts: true,
		};

		webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);

		webviewView.webview.onDidReceiveMessage(data => {
			myLog().info(data);

			switch (data.type) {
				case 'insertCode':
					{
						let imgItem = JSON.parse(data.data);
						vscode.window.activeTextEditor?.insertSnippet(new vscode.SnippetString(`${imgItem.basename}`));
						break;
					}
				case 'refresh':
					{
						let imgDirList = JSON.parse(data.data);

						const imageDirList: any[] = [];

						const imageSuffixs = vscode.workspace.getConfiguration().get<string[]>("images-preview-plugin.imageSuffix") || [];

						for (let index = 0; index < imgDirList.length; index++) {
							const item = imgDirList[index];
							myLog().info(`dirPath=${item.dirPath}`);
							let imgFileList = getFils([vscode.Uri.file(item.dirPath)], (filePath: string) => {
								const parsedPath = path.parse(filePath);
								if (imageSuffixs.indexOf(parsedPath.ext.toLowerCase()) > -1) {
									return true;
								} else {
									myLog().error(`Unsupported file type! ${filePath}`);
									return false;
								}
							});

							myLog().info(`imgs=${imgFileList}`);

							const imageFileList: any[] = [];
							imgFileList.forEach((value) => {
								imageFileList.push({
									imagePath: value,
									imageVsCodePath: webviewView.webview.asWebviewUri(vscode.Uri.file(value)).toString(),
									basename: path.basename(value)
								});
							});

							imageDirList.push({
								dirPath: item.dirPath,
								dirBaseName: path.basename(item.dirPath),
								chidler: imageFileList,
							});
						}
						webviewView.webview.postMessage({
							type: 'updateAll',
							data: imageDirList
						});
						break;
					}
			}
		});

	}

	public setting() {
		if (this._view) {
			this._view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders
			this._view.webview.postMessage({
				type: 'setting'
			});
		} else {
			console.log("failure");
		}
	}

	public refresh() {
		if (this._view) {
			this._view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders
			this._view.webview.postMessage({
				type: 'refresh'
			});
		} else {
			console.log("failure");
		}
	}

	public allDelt() {
		if (this._view) {
			this._view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders
			this._view.webview.postMessage({
				type: 'allDel'
			});
		} else {
			console.log("failure");
		}
	}

	public addImagesDir(dirPath: string, images: string[]) {
		if (this._view) {
			let view: vscode.WebviewView = this._view;
			const vscodeUrlList: any[] = [];
			images.forEach((value) => {
				vscodeUrlList.push({
					imagePath: value,
					imageVsCodePath: view.webview.asWebviewUri(vscode.Uri.file(value)).toString(),
					basename: path.basename(value)
				});
			});

			this._view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders
			this._view.webview.postMessage({
				type: 'addImagesDir', data: {
					dirPath,
					dirBaseName: path.basename(dirPath),
					chidler: vscodeUrlList,
				}
			});
		} else {
			console.log("failure");
		}
	}

	public addColor() {
		if (this._view) {
			this._view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders
			this._view.webview.postMessage({ type: 'addColor' });
		}
	}

	public clearColors() {
		if (this._view) {
			this._view.webview.postMessage({ type: 'clearColors' });
		}
	}


	private getNonce() {
		let text = '';
		const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
		for (let i = 0; i < 32; i++) {
			text += possible.charAt(Math.floor(Math.random() * possible.length));
		}
		return text;
	}

	private _getHtmlForWebview(webview: vscode.Webview) {

		const jsFilePath =
			vscode.Uri.joinPath(this._extensionUri, 'template', 'index-9d718c3e.js');
		const cssFilePath =
			vscode.Uri.joinPath(this._extensionUri, 'template', 'index-8c1ff1a5.css');

		// const requireFilePath =
		// 	vscode.Uri.joinPath(this._extensionUri, 'template', 'require.js');

		let jsUrl = webview.asWebviewUri(jsFilePath).toString();
		let cssUrl = webview.asWebviewUri(cssFilePath).toString();
		// let requireUrl = webview.asWebviewUri(requireFilePath).toString();

		const nonce = this.getNonce();

		//  let data=store.imagesMapStore.value;
		// 			data[e.data.name]=e.data.chidler;
		// 			store.imagesMapStore.value=data;
		// <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">


		return `<!DOCTYPE html>
		<html lang="en">
		  <head>
			<meta charset="UTF-8">
			<link rel="icon" href="/favicon.ico">
			
			<meta name="viewport" content="width=device-width, initial-scale=1.0">
			<title>Image Preview</title>
			
			<script type="module" crossorigin src="${jsUrl}"></script>
			
			<link rel="stylesheet" href="${cssUrl}">
		  </head>
		  <body  data-vscode-context='{"webviewSection": "editor", "preventDefaultContextMenuItems": true}'>
			<div id="app"></div>
		  </body>
		</html>`;

	}


}